package com.zking.utils;

import com.zking.dao.BaseDao;
import com.zking.entity.PageManager;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class DaoUtils extends BaseDao {

    /**
     * 获取插入sql语句与参数数组
     * @param obj 需要转化的实体类对象
     *//*
    public Map<String, Object> insertSQLandParams(Object obj){
        Map<String, Object> SQLandParamsMap = new HashMap<>();
        //0.获取这个对象的反射
        Class cls = obj.getClass();
        //1.创建字符串生成器
        StringBuilder sqlStr = new StringBuilder();
        sqlStr.append("insert into ").append(cls.getSimpleName()).append("(");
        //2.拼接表明后面的字段
        Field[] fields = cls.getDeclaredFields();
        //创建一个新的字符串生成，专门皮尼厄占位符
        StringBuilder placeholderStr = new StringBuilder();
        placeholderStr.append(" values(");
        //创建一个参数列表。参数的数量和字段的数量是一样的
        Object[] params = new Object[fields.length];
        for (int i = 0; i < fields.length; i++) {
            //拼接sql
            Field field = fields[i];
            sqlStr.append(field.getName()).append(",");
            placeholderStr.append("?,");
            //执行get方法取出值并放入到params数组
            String fieldName = field.getName();
            //通过执行get方法获取对象中的值
            params[i] = invokeGetter(fieldName, cls, obj);
        }
        //3.去掉最后一个逗号
        sqlStr.setLength(sqlStr.length()-1);
        sqlStr.append(")");
        placeholderStr.setLength(placeholderStr.length()-1);
        placeholderStr.append(")");
        //将占位符贫瘠额到主sql
        sqlStr.append(placeholderStr);
        //将两个对象存储到map集合中
        SQLandParamsMap.put("sql", sqlStr.toString());
        SQLandParamsMap.put("params", params);
        return SQLandParamsMap;
    }*/

    /**
     * 执行一个实体类中的 get方法
     * @param fieldName 字段名
     * @param cls 反射
     * @param obj 实体类的一个对象
     */
    public Object invokeGetter(String fieldName, Class cls, Object obj){
        try {
            //拼接get方法名
            String getMethodName = "get" + fieldName.substring(0,1).toUpperCase()
                    + fieldName.substring(1);
            //获取这个get方法对象
            Method getMethod = cls.getDeclaredMethod(getMethodName);
            //执行方法并返回
            return getMethod.invoke(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 保存一条数据(根据选定的参数key-value)
     */
    public boolean saveObject(String tableName, Map<String, Object> paramsMap){
        //拼接主sql
        StringBuilder sqlStr = new StringBuilder();
        //设置参数
        List<Object> paramsList = new ArrayList<>();
        sqlStr.append("insert into ").append(tableName).append("(");
        //拼接占位符
        StringBuilder placeholderStr = new StringBuilder();
        placeholderStr.append(" values(");
        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
            sqlStr.append(entry.getKey()).append(",");
            //拼接占位符
            placeholderStr.append("?,");
            paramsList.add(entry.getValue());
        }
        //去掉主sql的最后一个逗号
        sqlStr.setLength(sqlStr.length()-1);
        sqlStr.append(")");
        //去掉占位符的最后一个逗号
        placeholderStr.setLength(placeholderStr.length()-1);
        placeholderStr.append(")");
        //将占位符部分添加到主sql中
        sqlStr.append(placeholderStr);
        return update(sqlStr.toString(), paramsList.toArray()) > 0;
    }

    /**
     * 根据id更新一条数据(根据选定的参数key-value)
     */
    public boolean updateObject(String tableName, Map<String, Object> paramsMap){
        //拼接主sql
        StringBuilder sqlStr = new StringBuilder();
        //设置参数
        List<Object> paramsList = new ArrayList<>();
        sqlStr.append("update ").append(tableName).append(" set ");
        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
            sqlStr.append(entry.getKey()).append(" = ?,");
            paramsList.add(entry.getValue());
        }
        //去掉主sql的最后一个逗号
        sqlStr.setLength(sqlStr.length()-1);
        sqlStr.append(" where id = ?");
        paramsList.add(paramsMap.get("id"));
        return update(sqlStr.toString(), paramsList.toArray()) > 0;
    }

    /**
     * 根据id删除一条数据(id是字符串类型的)
     * <br>
     *     注意：必须要有主键id
     * @param tableName 表名
     * @param id 字符串的id
     */
    public boolean deleteById(String tableName, String id){
        return update("delete from "+tableName+" where id = ?",
                id) > 0;
    }

    /**
     * 根据id删除一条数据(id是int类型的)
     * <br>
     *     注意：必须要有主键id
     * @param tableName 表名
     * @param id int类型的id
     */
    public boolean deleteById(String tableName, int id){
        return update("delete from "+tableName+" where id = ?",
                id) > 0;
    }

    /**
     * 根据id查询一条数据并返回反射对应的实体类(参数id是字符串类型)
     */
    public <T> T queryObjectById(Class<T> cls, String id){
        return queryObject("select * from "+cls.getSimpleName()+" where id = ?",
                cls, id);
    }

    /**
     * 根据id查询一条数据并返回反射对应的实体类(参数id是int类型)
     */
    public <T> T queryObjectById(Class<T> cls, int id){
        return queryObjectById(cls, Integer.toString(id));
    }

    /**
     * 根据表名获取数据条数
     */
    public int getTotalCount(String tableName){
        return getTotalCountByConditions(tableName, null);
    }

    /**
     * 根据表名和条件查询对应数据条数
     */
    public int getTotalCountByConditions(String tableName,
                                         Map<String, Object> paramsMap){
        StringBuilder sqlStr = new StringBuilder();
        //存储参数
        List<Object> paramsList = new ArrayList<>();
        sqlStr.append("select count(*) from ")
                .append(tableName)
                .append(" where 1=1 ");
        //拼接where参数
        appendParams(paramsMap, sqlStr, paramsList);
        return NumberUtils.parseInt(queryScalar(sqlStr.toString(), paramsList.toArray()).toString());
    }

    /**
     * 根据条件查询多条数据（只支持and拼接）
     */
    public <T> List<T> queryObjectsByConditions(Class<T> cls,
                                                Map<String, Object> paramsMap,
                                                String order,
                                                PageManager pm){
        //拼接sql语句
        StringBuilder sqlStr = new StringBuilder();
        //存储参数
        List<Object> paramsList = new ArrayList<>();
        //拼接前面的sql语句，select * from 表名
        sqlStr.append("select * from ")
                .append(cls.getSimpleName())
                .append(" where 1=1 ");

        //拼接sql的where条件
        appendParams(paramsMap, sqlStr, paramsList);

        //先条件，再order，最后limit
        //如果排序字符串不为空，就拼接
        if (StringUtils.isNotBlank(order)) {
            sqlStr.append(" order by ").append(order);
        }

        //如果pm不为空，就拼接分页参数
        if (pm != null) {
            sqlStr.append(" limit ?,?");
            paramsList.add((pm.getPn() - 1)*pm.getRn());
            paramsList.add(pm.getRn());
        }
        return queryObjects(sqlStr.toString(), cls, paramsList.toArray());
    }

    public void appendParams(Map<String, Object> paramsMap,
                             StringBuilder sqlStr,
                             List<Object> paramsList){
        //拼接sql的where条件
        if (paramsMap != null) {
            for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
                if (entry.getValue() != null &&
                        StringUtils.isNotBlank(entry.getValue().toString())) {
                    //拼接sql
                    sqlStr.append(" and ").append(entry.getKey()).append(" = ? ");
                    //拼接参数
                    paramsList.add(entry.getValue());
                }
            }
        }
    }

    /**
     * 根据条件查询多条数据(不带排序)
     */
    public <T> List<T> queryObjectsByConditions(Class<T> cls,
                                                Map<String, Object> params,
                                                PageManager pm){
        return queryObjectsByConditions(cls, params, null, pm);
    }

    /**
     * 根据条件查询多条数据(查询所有数据)
     */
    public <T> List<T> queryObjectsByConditions(Class<T> cls){
        return queryObjectsByConditions(cls, null, null, null);
    }

    /**
     * 根据条件查询多条数据(不带分页)
     */
    public <T> List<T> queryObjectsByConditions(Class<T> cls,
                                                Map<String, Object> params,
                                                String order){
        return queryObjectsByConditions(cls, params, order, null);
    }

    /**
     * 根据条件查询多条数据(不带分页，不带排序)
     */
    public <T> List<T> queryObjectsByConditions(Class<T> cls,
                                                Map<String, Object> params){
        return queryObjectsByConditions(cls, params, null, null);
    }

    /**
     * 根据条件查询多条数据(不带排序，不带参数)
     */
    public <T> List<T> queryObjectsByConditions(Class<T> cls, PageManager pm){
        return queryObjectsByConditions(cls, null, null, pm);
    }

    /**
     * 根据条件查询多条数据
     */
    public <T> List<T> queryObjectsByConditions(Class<T> cls, String order){
        return queryObjectsByConditions(cls, null, order, null);
    }

    /**
     * 根据条件查询多条数据(不带排序，不带参数)
     */
    public <T> List<T> queryObjectsByConditions(Class<T> cls, String order, PageManager pm){
        return queryObjectsByConditions(cls, null, order, pm);
    }

    /**
     * 根据条件查询一条数据
     */
    public <T> T queryObjectByConditions(Class<T> cls, Map<String, Object> params){
        List<T> tList = queryObjectsByConditions(cls, params, null, null);
        return (tList != null && !tList.isEmpty()) ? tList.get(0) : null;
    }

}
